﻿using System;
using System.Linq.Expressions;
using System.Web;
using Common.Logging;
using TSharp.Core.Osgi;
using TSharp.Core.Pattern;
using TSharp.Core.Repository;
using TSharp.Core.Caching;
using TSharp.Core.Util;
namespace TSharp.Core
{
    /// <summary>
    /// AOP容器上下文
    /// <para>by tangjingbo at 2009-11-4 14:37</para>
    /// </summary>
    public sealed partial class AopContext
    {
        private static IServiceSituation serviceSituation;

        private AopContext()
        {
        }

        #region 获取和重新创建上下文

        private static object asynSituation = new object();

        /// <summary>
        /// aop上下文
        /// </summary>
        public static IServiceSituation Services
        {
            get
            {
                if (serviceSituation != null)
                    return serviceSituation;
                lock (asynSituation)
                {
                    if (serviceSituation == null)
                        serviceSituation = CreateServiceSituation();
                    return serviceSituation;
                }
            }
        }

        /// <summary>
        /// 重新创建服务访问上下文，返回原有上下文
        /// </summary>
        /// <returns></returns>
        public static IServiceSituation ResetServiceSituation()
        {
            lock (asynSituation)
            {
                IServiceSituation origin = serviceSituation;
                serviceSituation = CreateServiceSituation();
                return origin;
            }
        }

        #endregion

        /// <summary>
        /// 获取默认服务定位器
        /// </summary>
        /// <value>The default.</value>
        public static IServiceLocator GetDefaultLactor()
        {
            return Services.GetRequest();
        }

        /// <summary>
        /// Gets the HTTP context.
        /// </summary>
        /// <returns></returns>
        public static HttpContextBase GetHttpContext()
        {
            return httpContextFactory();
        }

        /// <summary>
        /// Sets the HTTP context factory.
        /// </summary>
        /// <param name="fac">The fac.</param>
        public static void SetHttpContextFactory(Expression<Func<HttpContextBase>> fac)
        {
            httpContextFactory = fac.Compile();
        }
        internal static readonly string Key_Request_ReadWriteUnitOfWork = "Key:Request:ReadWriteUnitOfWork".GetAppSetting("Key:Request:ReadWriteUnitOfWork");

        /// <summary>
        /// Begins the request unit of work.
        /// </summary>
        /// <returns></returns>
        internal static IUnitOfWork BeginRequestUnitOfWork()
        {
            return RequestUtil.GetOrAdd<IUnitOfWork>(Key_Request_ReadWriteUnitOfWork,
                k => GetUnitOfWorkFactory().BeginUnitOfWork().BeginAutoTransaction());
        }

        internal static readonly string Key_Request_ReadonlyUnitOfWork = "Key:Request:ReadonlyUnitOfWork".GetAppSetting("Key:Request:ReadonlyUnitOfWork");

        internal static IUnitOfWork BeginRequestReadonlyUnitOfWork()
        {
            return RequestUtil.GetOrAdd<IUnitOfWork>(Key_Request_ReadonlyUnitOfWork,
                k => GetUnitOfWorkFactory().BeginUnitOfWork(true));
        }

        internal static IUnitOfWorkFactory GetUnitOfWorkFactory()
        {
            return ThreadSingletonHelper<IUnitOfWorkFactory>.GetOrAdd(() => LazyLoading.New<IUnitOfWorkFactory>());
        }

        /// <summary>
        /// Queries this instance.
        /// </summary>
        /// <typeparam name="TSpecification">The type of the specification.</typeparam>
        /// <typeparam name="TEntity">The type of the entity.</typeparam>
        /// <returns></returns>
        public static TSpecification Query<TSpecification, TEntity>()
            where TEntity : class
            where TSpecification : class, ISpecification<TEntity>
        {
            return GetDefaultLactor().Get<IReadonlyRepository<TEntity, Guid>>().Specify<TSpecification>();
        }
    }
}